<?php
/**
 * @package mikrokosmos
 * mk script created on 28-giu-2005
 * jaco_at_pixeldump_dot_org
 */

if(!class_exists("MKTagHeader")){ class MKTagHeader {}}


/**
 * setBackGroundColor wrapper class
 */
class MKSetBackgroundColor extends MKTagHeader {

	var $color;

	// the constructor
	function MKSetBackgroundColor($tagData = "", $cAr = array()){

		if(strlen($tagData)){
			$this->tagData = $tagData;
			parent::MKTagHeader(substr($tagData, 0, 10));
			$this->get_setBackgroundColor_data();
			return;
		}

		$this->set_backgroundColor($cAr);
	}

	//
	function set_backgroundColor($bgColor) {
		if(!is_array($bgColor)) $cAr = get_color_array($bgColor);

		$this->color = MKColor();
		$this->color->set_color($bgColor);
	}

	function get_backgroundColor(){
		return $this->color->get_color();
	}

	//
	function set_setBackgroundColor_data(){
		$cAr = $this->color->get_color();
		$this->tagData = write_setBackgroundColor_data($cAr);
	}

	function get_setBackgroundColor_data(){
		$cAr = read_setBackGroundColor_data($this->tagData);
		$this->color = new MKColor();
		$this->color->set_color($cAr);
	}

	// alias of set_setBackgroundColor_data
	function update_tagData(){
		return $this->set_setBackgroundColor_data();
	}

	function fetch_assoc(){
		return $this->color->get_color();
	}

	function fetch_xml($includeHeader = true, $tabLevel = 0, $nodeName = "backgroundColor"){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		$xmlStr .= $pfx ."<" .$nodeName ." ";
		$cAr = $this->color->get_color();

		$xmlStr .= "color=\"" .get_html_color($cAr) ."\" />";

		return $xmlStr;
	}
}

/**
 * frame label wrapper class
 */
class MKFrameLabel extends MKTagHeader {

	var $tagdata = "";
	var $label = "";
	var $hasAnchor = 0;

	// the constructor
	function MKFrameLabel($tagData, $label = "", $hasAnchor = 0){

		if(strlen($tagData)){
			$this->tagData = $tagData;
			parent::MKTagHeader(substr($tagData, 0, 10));
			$this->get_frameLabel_data();
			return;
		}

		$this->label = $label;
		$this->hasAnchor = 0;
		$this->set_frameLabel_data();
	}

	function set_label($label) { $this->label = $label; }
	function get_label() { return $this->label; }

	function get_frameLabel_data(){
		$fld = array();
		$fld = read_frameLabel_data($this->tagData);
		$this->label = $fld["label"];
		if(isset($fld["hasAnchor"])) $this->hasAnchor = $fld["hasAnchor"];
	}

	function set_frameLabel_data(){
		$this->tagData = write_frameLabel_data($this->label, $this->hasAnchor);
		return $this->tagData;
	}

	// alias of set_frameLabel_data
	function update_tagData(){
		return $this->set_frameLabel_data();
	}


	function fetch_xml($includeHeader = true, $tabLevel = 0, $nodeName = "frameLabel"){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		$xmlNN = $this->hasAnchor ? $nodeName : "namedAnchor";
		$xmlStr .= $pfx ."<" .$xmlNN ." ";
		$xmlStr .= "name=\"" .$this->label ."\" />";

		return $xmlStr;
	}
}


/**
 *
 */
class MKEnableDebugger extends MKTagHeader{

	var $tagData = "";
	var $MD5password = "";
	var $debuggerVersion = DEBUGGER;
	var $plainPassWord = "";

	function MKEnableDebugger($tagData = "", $password = ""){

		if(strlen($tagData)){
			$this->tagData = $tagData;
			parent::MKTagHeader(substr($tagData, 0, 10));
			$this->get_enableDebugger_data();
		}

	}

	function set_MD5password($MD5password){ $this->MD5password = $MD5password; }
	function get_MD5password(){ return $this->MD5password; }

	function set_plainPassword($plainPassword){ $this->plainPassword = $plainPassword; }
	function get_plainPassword(){ return $this->plainPassword; }

	function set_debuggerVersion($debuggerVersion){ $this->debuggerVersion = $debuggerVersion; }
	function get_debuggerVersion(){ return $this->debuggerVersion; }

	function set_enableDebugger_data($edd = array()){
		if(!count($edd)) $edd = $this->fetch_assoc();

		$this->tagData = write_enableDebugger_data($edd);
		return $this->tagData;
	}

	function get_enableDebugger_data($edd = array()){

		if(!count($edd)) $edd = read_enableDebugger_data($this->tagData);

		$this->debuggerVersion = $edd["debuggerVersion"];
		$this->MD5password = $edd["MD5password"];
	}

	function fetch_assoc(){

		$edd = array();
		$edd["debuggerVersion"] = $this->debuggerVersion;
		if(strlen($this->plainPassword)) $this->MD5Password = md5($this->plainPassword);
		$edd["plainPassword"] = $this->plainPassword;
		$edd["MD5password"] = $this->MD5password;

		return $edd;
	}

	//
	function fetch_xml($includeHeader = true, $tabLevel = 0, $nodeName = "enableDebugger"){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		if($this->debuggerVersion == DEBUGGER2 && $nodeName == "enableDebugger") $nodeName .= "2";

		$xmlStr .= $pfx ."<" .$nodeName ." ";
		$xmlStr .= "MD5password=\"" .$this->MD5password ."\" />";

		return $xmlStr;
	}

	function update_tagData(){ return $this->set_enableDebugger_data(); }
}



/**
 * protect class wrapper
 */
class MKProtect extends MKTagHeader{

	var $tagData = "";
	var $MD5password = "";

	// the constructor
	function MKProtect($tagData = ""){

		if(strlen($tagData)){
			$this->tagData = $tagData;
			parent::MKTagHeader(substr($this->tagData, 0, 10));
			$this->get_protect_data();
			return;
		}
	}

	//
	function set_MD5password($MD5password) { $this->MD5password = $MD5password; }
	function get_MD5password() { return $this->MD5password; }

	function set_protect_data(){
		$this->tagData = write_protect_data($this->MD5password);
		return $this->tagData;
	}

	function get_protect_data(){
		$this->MD5password = read_protect_data($this->tagData);
	}

	// alias of set_protect_data
	function update_tagData(){
		return $this->set_protect_data();
	}

	//
	function fetch_xml($includeHeader = true, $tabLevel = 0, $nodeName = "protect"){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		$xmlStr .= $pfx ."<" .$nodeName ." ";
		$xmlStr .= "MD5password=\"" .$this->MD5password ."\" />";

		return $xmlStr;
	}
}


/**
 * export assets class wrapper
 * is used with linkage symbols
 */
class MKExportAssets extends MKTagHeader {

	var $tagData = "";
	var $assetCount = 0;
	var $assets = array();

	// the constructor
	function MKExportAssets($tagData = "", $assets = array()){

		if(strlen($tagData)){
			$this->tagData = $tagData;
			parent::MKTagHeader(substr($this->tagData, 0, 10));
			$this->get_exportAssets_data();
			return;
		}

		$this->assets = $assets;
		$this->assetCount = count($this->assets);
	}

	//
	function get_assetCount() { return $this->assetCount; }

	//
	function set_assets($assets) {
		$this->assets = $assets;
		$this->assetCount = count($this->assets);
	}
	function get_assets() { return $this->assets; }

	//
	function add_asset($assetID, $assetName = ""){
		$this->assetCount = count($this->assets);
		$ac = $this->assetCount;
		$this->assets[$ac] = array();
		$this->assets[$ac]["id"] = $assetID;
		$this->assets[$ac]["name"] = $assetName;
		$this->assetCount++;
	}

	//
	function update_asset($assetID = 0, $assetName = "", $index = 0){
		if(!isset($this->assets[$index])) $this->add_asset($assetID, $assetName);

		if($assetID > 0) $this->assets[$index]["id"] = $assetID;
		if(strlen($assetName)) $this->assets[$index]["name"] = $assetName;
	}

	//
	function get_assetAt($index){
		if(!isset($this->assets[$index])) return false;
		return $this->assets[$index];
	}

	function set_exportAssets_data($ead = array()){

		if(!count($ead)){
			$ead = $this->fetch_assoc();
		}

		$this->tagData = write_exportAssets_data($ead);
		return $this->tagData;
	}

	function get_exportAssets_data($ead = array()){

		if(!count($ead)){
			$ead = read_exportAssets_data($this->tagData);
		}

		$this->assetCount = $ead["assetCount"];
		$this->assets = $ead["assets"];
	}

	// alias of set_exportAssets_data
	function update_tagData($ead = array()){
		return $this->set_exportAssets_data();
	}

	function fetch_assoc(){
		$ead = array();
		$ead["assetCount"] = count($this->assets);
		$ead["assets"] = $this->assets;

		return $ead;
	}

	//
	function fetch_flasm($indentationLevel = 2){

		$il = $indentationLevel;
		$ilStr = str_repeat(" ", $il);

		$fStr = "";
		for($i = 0; $i < $this->assetCount; $i++){

			$ac = $this->assets[$i];
			$fStr = "\r\n" .$ilStr ."exportAssets";
			$fStr .= "\r\n" .$ilStr .(str_repeat(" ", 2)) .$ac["id"];
			$fStr .= " as '";
			$fStr .= $ac["name"] ."'";
			$fStr .= "\r\n" .$ilStr ."end // of exportAssets";
			$fStr .= "\r\n";
		}

		return $fStr;
	}

	//
	function fetch_xml($includeHeader = true, $tabLevel = 0, $nodeName = "linkage"){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		$xmlStr .= $pfx ."<" .$nodeName .">";
		$pfx = get_xml_indent_row(++$tabLevel);
		foreach($this->assets as $asset){
			$xmlStr .= $pfx ."<asset name=\"" .$asset["name"] ."\" ";
			$xmlStr .= "id=\"" .$asset["id"] ."\" />";
			//$xmlStr .= hex_dump($this->tagData, true);
			//$xmlStr .= "</asset>";
		}
		$pfx = get_xml_indent_row(--$tabLevel);
		$xmlStr .= $pfx ."</" .$nodeName .">";

		return $xmlStr;
	}


}


/**
 * import assets class wrapper
 * is used with linkage symbols
 * used from swf8
 */
class MKImportAssets2 extends MKTagHeader {

	var $tagData = "";

	var $url;				// URL STRING URL where the source SWF file can be found
	var $reserved1 = 1;		// UI8 Must be 1
	var $reserved0 = 0;		// UI8 Must be 0
	var $assetCount = 0;	// UI16 Number of assets to import
	var $assets = array();

	// the constructor
	function MKImportAssets2($tagData = "", $assets = array()){

		if(strlen($tagData)){
			$this->tagData = $tagData;
			parent::MKTagHeader(substr($this->tagData, 0, 10));
			$this->get_importAssets_data();
			return;
		}

		$this->assets = $assets;
		$this->assetCount = count($this->assets);
	}

	//
	function set_url($url) { $this->url = $url; }
	function get_url() { return $this->url; }

	//
	function get_assetCount() { return $this->assetCount; }

	//
	function set_assets($assets) {
		$this->assets = $assets;
		$this->assetCount = count($this->assets);
	}
	function get_assets() { return $this->assets; }

	//
	function add_asset($assetID, $assetName){
		$this->assetCount = count($this->assets);
		$ac = $this->assetCount;
		$this->assets[$ac] = array();
		$this->assets[$ac]["id"] = $assetID;
		$this->assets[$ac]["name"] = $assetName;
		$this->assetCount++;
	}

	function set_importAssets_data($ead = array()){

		if(!count($ead)){
			$ead = $this->fetch_assoc();
		}

		$this->tagData = write_importAssets2_data($ead);
		return $this->tagData;
	}

	function get_importAssets2_data($ead = array()){

		if(!count($ead)){
			$ead = read_importAssets2_data($this->tagData);
		}

		$this->url = $ead["url"];
		$this->assetCount = $ead["assetCount"];
		$this->assets = $ead["assets"];
	}

	// alias of set_importAssets2_data
	function update_tagData($ead = array()){
		return $this->set_importAssets2_data();
	}

	function fetch_assoc(){
		$ead = array();
		$ead["url"] = $this->url;
		$ead["assetCount"] = count($this->assets);
		$ead["assets"] = $this->assets;

		return $ead;
	}

	//
	function fetch_flasm($indentationLevel = 2){

		$il = $indentationLevel;
		$ilStr = str_repeat(" ", $il);

		$fStr = "";
		for($i = 0; $i < $this->assetCount; $i++){

			$ac = $this->assets[$i];
			$fStr = "\r\n" .$ilStr ."importAssets2";
			$fStr .= "\r\n" .$ilStr .(str_repeat(" ", 2)) .$ac["id"];
			$fStr .= " as '";
			$fStr .= $ac["name"] ."'";
			$fStr .= "\r\n" .$ilStr ."end // of importAssets2";
			$fStr .= "\r\n";
		}

		return $fStr;
	}

	//
	function fetch_xml($includeHeader = true, $tabLevel = 0, $nodeName = "linkage"){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		$xmlStr .= $pfx ."<" .$nodeName ."";
		if(strlen($this->url)){
			$xmlStr .= " url=\"";
			$xmlstr .= $this->url ."\"";
		}
		$xmlStr .= ">";
		$pfx = get_xml_indent_row(++$tabLevel);
		foreach($this->assets as $asset){
			$xmlStr .= $pfx ."<asset name=\"" .$asset["name"] ."\" ";
			$xmlStr .= "id=\"" .$asset["id"] ."\" >";
			$xmlStr .= hex_dump($this->tagData, true);
			$xmlStr .= "</asset>";
		}
		$pfx = get_xml_indent_row(--$tabLevel);
		$xmlStr .= $pfx ."</" .$nodeName .">";

		return $xmlStr;
	}
}

/**
 * placeobject2 class
 */
class MKPlaceObject2 extends  MKTagHeader {

	var $tagData;

	// pf means: PlaceFlag
	var $pfHasClipActions	 = 0;	// UB[1] SWF 5 and later: has clip
									// actions (sprite characters only)
									// Otherwise: always 0

	var $pfHasClipDepth		 = 0;	// UB[1] Has clip depth
	var $pfHasName			 = 0;	// UB[1] Has name
	var $pfHasRatio			 = 0;	// UB[1] Has ratio
	var $pfHasColorTransform = 0;	// UB[1] Has color transform
	var $pfHasMatrix		 = 0;	// UB[1] Has matrix
	var $pfHasCharacter		 = 1;	// UB[1] Places a character
	var $pfMove				 = 0;	// UB[1] Defines a character to be moved

	var $depth				 = 1;	// UI16 Depth of character
	var $characterID		 = 1;	// If PlaceFlagHasCharacter UI16 ID of character to place
	var $matrix;					// If PlaceFlagHasMatrix MATRIX Transform matrix data
	var $colorTransform;			// If PlaceFlagHasColorTransform CXFORMWITHALPHA Color transform data
	var $ratio;						// If PlaceFlagHasRatio UI16
	var $name;						// If PlaceFlagHasName STRING Name of character
	var $clipDepth;					// If PlaceFlagHasClipDepth UI16 Clip depth (see Clipping Layers)
	var $clipActions;				// If PlaceFlagHasClipActions CLIPACTIONS SWF 5 and later: Clip Actions Data
									// clipActions are stored in its original bytecode

	var $caObj;						// clipActions stored as MKClipActionsContainer class

	// the constructor
	function MKPlaceObject2($tagData = "",
							 $depth = 1,
							 $characterID = 1,
							 $matrixData = array(),
							 $cwad = array(),
							 $ratio = 0,
							 $name = "",
							 $clipDepth = 0,
							 $caData = array()){

		$this->tagData = $tagData;

		if(strlen($tagData)){
			$this->get_placeObject2_data();
			return;
		}

		$this->depth = $depth;
		$this->characterID = $characterID;

		// matrix data
		if(count($matrixData))
			$this->add_matrix($matrixData);

		// cxformwithalpha data
		if(count($cwad)){
			$this->colorTransform = new MKCxformWithAlpha("", $cwad);
		}

		$this->ratio = $ratio;
		$this->name = $name;
		$this->clipDepth = $clipDepth;

		// clipactions data
		if(count($caData)){
			$swfVersion = get_global_swfVersion();
			$this->clipActions = new MKClipActionsContainer("",
															$caData,
															$swfVersion,
															false);
		}
	}

	//
	function set_matrix($matrixObj){ $this->matrix = $matrixObj; }
	function get_matrix(){ return $this->matrix; }

	//
	function set_depth($depth){	$this->depth = $depth; }
	function get_depth(){ return $this->depth; }

	//
	function set_clipDepth($clipDepth = 1){
		$this->pfHasClipDepth = true;
		$this->clipDepth = $clipDepth;
	}
	function get_clipDepth(){ return $this->clipDepth; }

	//
	function set_clipActions($caBuf) {$this->clipActions = $caBuf; }
	function get_clipActions(){ return $this->clipActions; }

	//
	function set_characterID($characterID = 1){
		$this->pfHasCharacter = true;
		$this->characterID = $characterID;
	}
	function get_characterID(){ return $this->characterID; }

	//
	function set_ratio($ratio){
		$this->pfHasRatio = 1;
		$this->ratio = $ratio;
	}
	function get_ratio(){ return $this->ratio; }

	//
	function set_name($name){
		$this->pfHasName = 1;
		$this->name = $name;
	}
	function get_name(){ return $this->name; }

	//
	function set_pfMove($pfMove){	$this->pfMove = $pfMove; }
	function get_pfMove(){ return $this->pfMove; }


	//
	function set_position($x = 0, $y = 0, $depthFlag = false, $isChange = false){
		if($depthFlag) $this->depth++;
		if(!$this->matrix) $this->add_matrix();
		$this->matrix->set_position($x, $y);
		$this->check_change($isChange);

		//return $this->update_tagData();
	}

	function set_scale($scaleX = 100, $scaleY = 100, $depthFlag = false, $isChange = false){
		if($depthFlag) $this->depth++;
		if(!$this->matrix) $this->add_matrix();
		$this->matrix->set_scale($scaleX, $scaleY);
		$this->check_change($isChange);

		//return $this->update_tagData();
	}

	//
	function set_rotation($rotation = 0, $depthFlag = false, $isChange = false){
		if($depthFlag) $this->depth++;
		if($rotation >= 360) $rotation = $rotation % 360;
		if($rotation > 180) $rotation -= 360;
		if(!$this->matrix) $this->add_matrix();
		$this->matrix->set_rotation($rotation);
		$this->check_change($isChange);

		//return $this->update_tagData();
	}

	//
	function clear_transform_matrix(){
		unset($this->matrix);
		$this->pfHasMatrix = 0;
	}

	//
	function set_brightness($amount){
		/* TODO set_brightness*/
	}

	//
	function set_color_tranform($ctArray = array(), $isChange = false){
		/* TODO set_color_tranform*/

		$this->check_change($isChange);
	}

	//
	function set_alpha($alpha, $isChange = false){
		/* TODO set_alpha*/
		if($isChange){
			$this->pfMove = 1;
			$this->pfHasCharacter = 0;
		}
	}

	//
	function set_tint($tArray = array(), $isChange = false){
		/* TODO set_tint*/
		$this->check_change($isChange);
	}

	//
	function clear_color_tranform($isChange = false){
		unset($this->colorTransform);
		$this->pfHasColorTransform = 0;
		$this->check_change($isChange);
	}

	//
	function add_matrix($mad = array()){
		$this->matrix = new MKMatrix();
		$this->pfHasMatrix = 1;
		if(isset($mad["a"])) $this->matrix->build_matrix_from_array($mad);
		else if(count($mad)) $this->matrix->get_matrixdata($mad);
	}

	//
	function check_change($isChange = false){

		if(!$isChange) return;

		$this->pfMove = 1;
		$this->pfHasCharacter = 0;
	}

	//
	function set_placeObject2_data($pod = array()){

		if(!count($pod)) $pod = $this->fetch_assoc();

		$this->get_placeObject2_data($pod);
		$this->tagData = write_placeObject2_data($pod);

		return $this->tagData;
	}

	function get_placeObject2_data($pod = array()){

		if(!count($pod)) $pod = read_placeObject2_data($this->tagData);

		$this->pfHasClipActions 	= $pod["pfHasClipActions"];
		$this->pfHasClipDepth		= $pod["pfHasClipDepth"];
		$this->pfHasName			= $pod["pfHasName"];
		$this->pfHasRatio			= $pod["pfHasRatio"];
		$this->pfHasColorTransform	= $pod["pfHasColorTransform"];
		$this->pfHasMatrix			= $pod["pfHasMatrix"];
		$this->pfHasCharacter		= $pod["pfHasCharacter"];
		$this->pfMove				= $pod["pfMove"];

		$this->depth = $pod["depth"];

		if($pod["pfHasCharacter"]) $this->characterID = $pod["characterID"];

		if($pod["pfHasMatrix"]){
			$this->matrix	= new MKMatrix();
			$this->matrix->get_matrix_data($pod["matrix"]);
		}

		if($pod["pfHasColorTransform"])
			$this->colorTransform	= new MKCxformWithAlpha("", $pod["colorTransform"]);

		if($pod["pfHasRatio"]) $this->ratio = $pod["ratio"];
		if($pod["pfHasName"]) $this->name	= $pod["name"];
		if($pod["pfHasClipDepth"]) $this->clipDepth = $pod["clipDepth"];

		if($pod["pfHasClipActions"]){
			$this->clipActions = $pod["caBuf"];
			$this->caObj = new MKClipActionsContainer($this->clipActions);
		}

		return $pod;
	}

	//
	function fetch_assoc(){

		$pod = array();

		$pod["pfHasClipActions"]	= $this->pfHasClipActions;
		$pod["pfHasClipDepth"]		= $this->pfHasClipDepth;
		$pod["pfHasName"]			= $this->pfHasName;
		$pod["pfHasRatio"]			= $this->pfHasRatio;
		$pod["pfHasColorTransform"]	= $this->pfHasColorTransform;
		$pod["pfHasMatrix"]			= $this->pfHasMatrix;
		$pod["pfHasCharacter"]		= $this->pfHasCharacter;
		$pod["pfMove"]				= $this->pfMove;

		$pod["depth"]				= $this->depth;

		if($this->pfHasCharacter) $pod["characterID"] = $this->characterID;
		if($this->pfHasMatrix) {
			$pod["matrix"] = $this->matrix->fetch_assoc(true);
		}
		if($this->pfHasColorTransform) $pod["colorTransform"]	= $this->colorTransform->fetch_assoc();
		if($this->pfHasRatio) $pod["ratio"]	= $this->ratio;
		if($this->pfHasName) $pod["name"] = $this->name;
		if($this->pfHasClipDepth) $pod["clipDepth"] = $this->clipDepth;
		if($this->pfHasClipActions) $pod["clipActions"] = $this->clipActions;

		return $pod;
	}

	//
	function fetch_xml($includeHeader = true, $tabLevel = 0, $nodeName = "placeObject2"){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		$xmlStr .= $pfx ."<" .$nodeName ." ";

		//$xmlStr .= "pfHasClipDepth=\"" .($this->pfHasClipDepth ? "1\" " : "0\" ");
		//$xmlStr .= "pfHasName=\"" .($this->pfHasName ? "1\" " : "0\" ");
		//$xmlStr .= "pfHasRatio=\"" .($this->pfHasRatio ? "1\" " : "0\" ");
		if($this->pfHasColorTransform) $xmlStr .= "pfHasColorTransform=\"1\" ";
		//$xmlStr .= "pfHasMatrix=\"" .($this->pfHasMatrix ? "1\" " : "0\" ");
		//$xmlStr .= "pfHasCharacter=\"" .($this->pfHasCharacter ? "1\" " : "0\" ");

		if($this->pfMove) $xmlStr .= "pfMove=\"true\" ";

		$xmlStr .= "depth=\"" .$this->depth ."\" ";
		if($this->pfHasCharacter) $xmlStr .= "characterID=\"" .$this->characterID ."\" ";
		if($this->pfHasRatio) $xmlStr .= "ratio=\"" .$this->ratio ."\" ";
		if($this->pfHasName) $xmlStr .= "name=\"" .$this->name ."\" ";
		if($this->pfHasClipDepth) $xmlStr .= "clipDepth=\"" .$this->clipDepth ."\"";

		$xmlStr .= ">";

		if($this->pfHasMatrix) $xmlStr .= $this->matrix->fetch_xml(false, $tabLevel);

		/* TODO, implement these methods*/
		//if($this->pfHasColorTransform) $xmlStr .= $this->colorTransform->fetch_xml(false, $tabLevel);
		if($this->pfHasClipActions){
			$xmlStr .= $this->caObj->fetch_xml(false, $tabLevel);
		}

		$xmlStr .= $pfx ."<hexData>";
		$xmlStr .= hex_dump($this->tagData, true);
		$xmlStr .= "</hexData>";

		$xmlStr .= $pfx ."</" .$nodeName .">";
		return $xmlStr;
	}


	//
	function fetch_flasm($indentationLevel = 2){

		if(!$this->pfHasClipActions) return "";

		$il = $indentationLevel;	// indentation level
		$ilStr = str_repeat(" ", $il);

		$fStr = "\r\n" .$ilStr ."placeMovieClip ";
		$fStr .= $this->characterID;
		if($this->pfHasName){
			$fStr .= " as '";
			$fStr .= $this->name ."'";
		}
		$fStr .= "\r\n";

		$il += 2;
		$ilStr = str_repeat(" ", $il);

		$fStr .= $this->caObj->fetch_flasm($il);

		$il -= 2;
		$ilStr = str_repeat(" ", $il);

		$fStr .= $ilStr ."end // of placeMovieClip ";
		$fStr .= $this->characterID;
		$fStr .= "\r\n";

		return $fStr;
	}

	//
	function update_tagData($replacingDepth = -1){
		if($replacingDepth > 0){
			$this->pfMove = 1;
			$this->depth = $replacingDepth;
		}
		return $this->set_placeObject2_data();
	}
}


/**
 * >= swf8
 */
class MKPlaceObject3 extends MKPlaceObject2 {

	var $pfHasClassRef = false;
	var $pfHasImage = false;
	var $classRef = "";

	var $pfHasCacheAsBitmap = false;
	var $pfHasBlendMode = false;
	var $pfHasFilterList = false;

	var $blendMode = 0;				 // normal blend mode
	var $filterList = array();

	var $swfVersion;

	// the constructor
	function MKPlaceObject3($tagData = "",  $depth = 1, $characterID = 1, $classRef = 1, $pfHasImage = false){

		$this->swfVersion = get_global_swfVersion();
		$this->pfHasCharacter = 0;	// UB[1] Places a character

		$this->tagData = $tagData;
		$this->depth = $depth;
		$this->charaterID = $characterID;
		$this->classRef = $classRef;
		$this->pfHasImage = $pfHasImage;

		if(strlen($tagData)) {
			$this->get_placeObject3_data();
			return;
		}

		if($classRef) $this->set_classRef($classRef, $pfHasImage);
	}

	//
	function set_classRef($classRef, $pfHasImage = false){
		$this->classRef = $classRef;
		$this->pfHasCharacter = true;

		$this->pfHasImage = $pfHasImage;
		if($pfHasImage) $this->pfHasClassRef = false;
	}
	function get_classRef() { return $this->classRef; }

	//
	function set_pfHasImage($pfHasImage) { $this->pfHasImage = $pfHasImage; }
	function get_pfHasImage() { return $this->pfHasImage; }

	//
	function set_pfHasCacheAsBitmap($pfHasCacheAsBitmap) { $this->pfHasCacheAsBitmap = $pfHasCacheAsBitmap; }
	function get_pfHasCacheAsBitmap() { return $this->pfHasCacheAsBitmap; }

	//
	function set_blendMode($blendMode) {
		$this->blendMode = $blendMode;
		$this->pfHasBlendMode = $blendMode == BLEND_NORMAL ? false : true;
	}
	function get_blendMode() { return $this->blendMode; }

	//
	function set_filterList($filterList) {
		$this->filterList = $filterList;
		$this->pfHasfilterList = count($filterList) ? true : false;
	}
	function get_filterList() { return $this->filterList; }


	//
	function set_placeObject3_data($po3d = array()){

		if(!count($po3d)) $po3d = $this->fetch_assoc();

		$this->get_placeObject3_data($po3d);
		$this->tagData = write_placeObject3_data($po3d);

		return $this->tagData;
	}

	function get_placeObject3_data($po3d = array()){

		if(!count($po3d)) $po3d = read_placeObject3_data($this->tagData);

		$this->swfVersion			= $po3d["swfVersion"];
		$this->pfHasClipActions 	= $po3d["pfHasClipActions"];
		$this->pfHasClipDepth		= $po3d["pfHasClipDepth"];
		$this->pfHasName			= $po3d["pfHasName"];
		$this->pfHasRatio			= $po3d["pfHasRatio"];
		$this->pfHasColorTransform	= $po3d["pfHasColorTransform"];
		$this->pfHasMatrix			= $po3d["pfHasMatrix"];
		$this->pfHasCharacter		= $po3d["pfHasCharacter"];
		$this->pfMove				= $po3d["pfMove"];

		$this->pfHasImage = $po3d["pfHasImage"];
		$this->pfHasClassRef = $po3d["pfHasClassRef"];
		$this->pfHasCacheAsBitmap = $po3d["pfHasCacheAsBitmap"];
		$this->pfHasBlendMode = $po3d["pfHasBlendMode"];
		$this->pfFilterList = $po3d["pfHasFilterList"];

		if($po3d["pfHasClassRef"] || ($po3d["pfHasImage"] && $po3d["pfHasCharacter"]))
			$this->classRef = $po3d["classRef"];

		if($po3d["pfHasFilterList"])
			$this->filterList = $po3d["filterList"];

		if($po3d["pfHasBlendMode"])
			$this->blendMode = $po3d["blendMode"];

		$this->depth = $po3d["depth"];

		if($po3d["pfHasCharacter"] && $po3d["swfVersion"] < 9)
			$this->characterID = $po3d["characterID"];

		if($po3d["pfHasMatrix"]){
			$this->matrix	= new MKMatrix();
			$this->matrix->get_matrix_data($po3d["matrix"]);
		}

		if($po3d["pfHasColorTransform"])
			$this->colorTransform	= new MKCxformWithAlpha("", $po3d["colorTransform"]);

		if($po3d["pfHasRatio"]) $this->ratio = $po3d["ratio"];
		if($po3d["pfHasName"]) $this->name	= $po3d["name"];
		if($po3d["pfHasClipDepth"]) $this->clipDepth = $po3d["clipDepth"];

		if($po3d["pfHasClipActions"]){
			$this->clipActions = $po3d["caBuf"];
			$this->caObj = new MKClipActionsContainer($this->clipActions);
		}

		return $po3d;
	}


	//
	function fetch_assoc(){

		$po3d = parent::fetch_assoc();
		$po3d["pfHasImage"] = $this->pfHasImage;
		$po3d["pfHasClassRef"] = $this->pfHasClassRef;
		$po3d["pfHasCacheAsBitmap"] = $this->pfHasCacheAsBitmap;
		$po3d["pfHasBlendMode"] = $this->pfHasBlendMode;
		$po3d["pfHasFilterList"] = $this->pfHasFilterList;

		if($this->pfHasClassRef || ($this->pfHasImage && $this->pfHasCharacter))
			$po3d["classRef"] = $this->classRef;

		if($this->pfHasFilterList)
			$po3d["filterList"] = $this->filterList;

		if($this->pfHasBlendMode)
			$po3d["blendMode"] = $this->blendMode;

		$po3d["swfVersion"] = $this->swfVersion;

		return $po3d;
	}

	//
	function fetch_xml($includeHeader = true, $tabLevel = 0, $nodeName = "placeObject3"){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		$xmlStr .= $pfx ."<" .$nodeName ." ";

		if($this->pfHasColorTransform) $xmlStr .= "pfHasColorTransform=\"1\" ";
		$xmlStr .= "pfMove=\"" .($this->pfMove ? "1\" " : "0\" ");

		$xmlStr .= "depth=\"" .$this->depth ."\" ";
		if($this->swfVersion < 9) if($this->pfHasCharacter) $xmlStr .= "characterID=\"" .$this->characterID ."\" ";
		if($this->pfHasRatio) $xmlStr .= "ratio=\"" .$this->ratio ."\" ";
		if($this->pfHasName) $xmlStr .= "name=\"" .$this->name ."\" ";
		if($this->pfHasClipDepth) $xmlStr .= "clipDepth=\"" .$this->clipDepth ."\" ";
		if($this->pfHasClassRef || ($this->pfHasImage && $this->pfHasCharacter)) $xmlStr .= "classRef=\"" .$this->classRef ."\" ";
		if($this->pfHasClassRef && $this->pfHasImage) $xmlStr .= "bitmapClass=\"1\" ";
		if($this->pfHasCacheAsBitmap) $xmlStr .= "cacheAsBitmap=\"1\" ";
		if($this->pfHasBlendMode) $xmlStr .= "clipDepth=\"" .get_blendMode($this->blendMode) ."\" ";
		if($this->pfHasFilterList) $xmlStr .= "filterList=\"hardcoded filter list is not yet implemented\" ";

		$xmlStr .= ">";

		if($this->pfHasMatrix) $xmlStr .= $this->matrix->fetch_xml(false, $tabLevel);

		/* TODO, implement these methods*/
		//if($this->pfHasColorTransform) $xmlStr .= $this->colorTransform->fetch_xml(false, $tabLevel);
		if($this->pfHasClipActions){
			$xmlStr .= $this->caObj->fetch_xml(false, $tabLevel);
		}

		$xmlStr .= $pfx ."<hexData>";
		$xmlStr .= hex_dump($this->tagData, true);
		$xmlStr .= "</hexData>";

		$xmlStr .= $pfx ."</" .$nodeName .">";
		return $xmlStr;
	}

	//
	function update_tagData(){
		return $this->set_placeObject3_data();
	}

}


/**
 * removeObject2 class wrapper
 */
class MKRemoveObject2 extends MKTagHeader {

	var $tagData = "";
	var $depth = 0;

	// the constructor
	function MKRemoveObject2($tagData = "", $depth = 0){

		if(strlen($tagData)){
			$this->tagData = $tagData;
			parent::MKTagHeader(substr($this->tagData, 0, 10));
			$this->get_removeObject2_data();
			return;
		}

		$this->depth = $depth;
		$this->set_removeObject2_data();
	}

	//
	function set_depth($depth) { $this->depth = $depth; }
	function get_depth() { return $this->depth; }

	function set_removeObject2_data(){
		$this->tagData = write_removeObject2_data($this->depth);
		return $this->tagData;
	}

	function get_removeObject2_data(){
		$this->depth = read_removeObject2_data($this->tagData);
	}

	// alias of set_frameLabel_data
	function update_tagData(){
		return $this->set_removeObject2_data();
	}

	//
	function fetch_xml($includeHeader = true, $tabLevel = 0, $nodeName = "removeObject2"){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		$xmlStr .= $pfx ."<" .$nodeName ." ";
		$xmlStr .= "depth=\"" .$this->depth ."\" />";

		return $xmlStr;
	}
}

// --------------------------------------
// these class are available from swf8

/**
 * FileAttributes
 * tagCode 69
 * Appears as first tag in the SWF file. Data length is always 5 bytes
 * Consists of flags, of which five are known:
 *
 * bit 0: specifies if SWF contains metadata
 * bit 1: specifies if SWF contains actionscript3
 * bit 2: suppress cross domain caching
 * bit 3: relative urls
 * bit 4: local playback security: local files (0) / network (1)
 */
class MKFileAttributes extends MKTagHeader {

	var $tagData = "";

	var $containsMetaData = false;
	var $containsAS3 = false;
	var $suppressCDC = false;
	var $relativeURLs = false;
	var $lpSecurity = false;

	var $reserved = 0;

	// the constructor
	function MKFileAttributes($tagData = "", $faData = array()){

		$this->tagData = $tagData;
		$this->get_fileAttributes_data($faData);
	}

	//
	function set_containsMetaData($cmdFlag) { $this->containsMetaData = $cmdFlag; }
	function get_containsMetaData() { return $this->containsMetaData; }

	//
	function set_containsAS3($cas3Flag) { $this->containsAS3 = $cas3Flag; }
	function get_containsAS3() { return $this->containsAS3; }

	//
	function set_suppressCDC($scdcFlag) { $this->suppressCDC = $scdcFlag; }
	function get_suppressCDC() { return $this->suppressCDC; }

	//
	function set_relativeURLs($ruFlag) { $this->relativeURLs = $ruFlag; }
	function get_relativeURLs() { return $this->relativeURLs; }

	//
	function set_lpSecurity($lpsFlag) { $this->lpSecurity = $lpsFlag; }
	function get_lpSecurity() { return $this->lpSecurity; }

	//
	function set_fileAttributes_data($faData = array()){

		if(!count($faData)){
			$faData = $this->fetch_assoc();
		}

		$this->tagData = write_fileAttributes_data($faData);
		return $this->tagData;
	}

	//
	function get_fileAttributes_data($faData = array()){

		if(!count($faData)){

			if(!strlen($this->tagData)) return;

			$faData = read_fileAttributes_data($this->tagData);
		}

		$this->containsMetaData = $faData["containsMetaData"];
		$this->containsAS3		= $faData["containsAS3"];
		$this->suppressCDC		= $faData["suppressCDC"];
		$this->relativeURLs		= $faData["relativeURLs"];
		$this->lpSecurity		= $faData["lpSecurity"];
	}

	//
	function fetch_assoc(){

		$faData = array();

		$faData["containsMetaData"] = $this->containsMetaData;
		$faData["containsAS3"]		= $this->containsAS3;
		$faData["suppressCDC"]		= $this->suppressCDC;
		$faData["relativeURLs"]		= $this->relativeURLs;
		$faData["lpSecurity"]		= $this->lpSecurity;

		return $faData;
	}

	//
	function fetch_xml($includeHeader = true, $tabLevel = 0, $nodeName = "fileAttributes"){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		$xmlStr .= $pfx ."<" .$nodeName;

		if($this->containsMetaData)
			$xmlStr .= " containsMetaData=\"1\"";

		if($this->containsAS3)
			$xmlStr .= " containsAS3=\"1\"";

		if($this->suppressCDC)
			$xmlStr .= " suppressCrossDomainCaching=\"1\"";

		if($this->relativeURLs)
			$xmlStr .= " relativeURLs=\"1\"";

		if($this->lpSecurity)
			$xmlStr .= " localPlayerSecurity=\"1\"";

		$xmlStr .= " />";

		return $xmlStr;
	}

	//
	function update_tagData(){
		return $this->set_fileAttributes_data();
	}
}

/**
 *
 */
class MKMetadata extends MKTagHeader {

	var $tagData = "";
	var $metadata = "";

	// the constructor
	function MKMetadata($tagData = "", $metadata = ""){

		if(strlen($tagData)){
			$this->buf = $tagData;
			$this->get_metadata_data();
		}
		else if(strlen($metadata)){
			$this->metadata = $metadata;
			$this->set_metadata_data();
		}
	}

	//
	function set_metadata($metadata) { $this->metadata = $metadata; }
	function get_metadata() { return $this->metadata; }

	function set_metadata_data(){
		$this->tagData = write_metadata_data($this->metadata);
		return $this->tagData;
	}

	function get_metadata_data(){
		$this->metadata = read_metadata_data($this->tagData);
	}

	// note: usual fetch_assoc is pointless in this contest

	//
	function fetch_xml($includeHeader = true, $tabLevel = 0, $nodeName = "metadata"){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);
		$xmlStr .= $pfx ."<" .$nodeName .">";
		$pfx = get_xml_indent_row(++$tabLevel);
		$xmlStr .= $pfx .$this->metadata;
		$pfx = get_xml_indent_row(--$tabLevel);
		$xmlStr .= $pfx ."</" .$nodeName .">";

		return $xmlStr;
	}

	//
	function update_tagData() {
		return $this->set_metadata_data();
	}
}

/**
 *
 */
class MKScriptLimits extends MKTagHeader {

	var $tagData = "";
	var $maxRecursionDepth;		// UI16 Maximum recursion depth
	var $scriptTimeoutSeconds;	// UI16 Maximum ActionScript
								// processing time before
								// script stuck dialog box displays

	function MKScriptLimits($tagData = "", $sld = array()){
		$this->tagData = $tagData;
		$this->get_scriptLimits_data($sld);
	}

	//
	function set_maxRecursionDepth($mrd) {$this->maxRecursionDepth = $mrd; }
	function get_maxRecursionDepth() { return $this->maxRecursionDepth; }

	//
	function set_scriptTimeoutSeconds($sts) { $this->scriptTimeoutSeconds = $sts; }
	function get_scriptTimeoutSeconds() { return $this->scriptTimeoutSeconds; }

	function set_scriptLimits_data($sld = array()){

		if(count($sld)) $this->get_scriptLimits_data($sld);
		else $sld = $this->fetch_assoc();

		$this->binData = write_scriptLimits_data($sld);

		return $this->tagData;
	}

	function get_scriptLimits_data($sld = array()){

		if(!count($sld)) $sld = read_scriptLimits_data($this->tagData);

		$this->maxRecursionDepth = $sld["maxRecursionDepth"];
		$this->scriptTimeoutSeconds = $sld["scriptTimeoutSeconds"];
	}

	//
	function fetch_assoc(){
		$sld = array();

		$sld["maxRecursionDepth"] = $this->maxRecursionDepth;
		$sld["scriptTimeoutSeconds"] = $this->scriptTimeoutSeconds;

		return $sld;
	}

	//
	function fetch_xml($includeHeader = true, $tabLevel = 0, $nodeName = "scriptLimits"){

		$zrd = $this->fetch_assoc();
		$xmlStr = $includeHeader ? XML_HEADER : "";

		$pfx = get_xml_indent_row(++$tabLevel);
		$xmlStr .= $pfx ."<" .$nodeName ." ";

		$xmlStr .= "maxRecursionDepth=\"" . $zrd["maxRecursionDepth"] ."\" ";
		$xmlStr .= "scriptTimeoutSeconds=\"" . $zrd["scriptTimeoutSeconds"] ."\" />";

		return $xmlStr;
	}

	//
	function update_tagData(){ return $this->set_scriptLimits_data(); }
}
// ------ end of mk classes - tags --------------------
?>
